﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 异步锁
    /// </summary>
    public class AsyncLocker
    {
        //字段
        private readonly Task<Releaser> _releaser;
        private readonly AsyncSemaphore _semaphore;

        /// <summary>
        /// 初始化一个异步锁（<see cref="AsyncLocker"/>）的新实例
        /// </summary>
        public AsyncLocker()
        {
            _semaphore = new AsyncSemaphore(1);
            _releaser = Task.FromResult(new Releaser(this));
        }

        /// <summary>
        /// 异步锁定
        /// </summary>
        public Task<Releaser> LockAsync()
        {
            var wait = _semaphore.WaitAsync();
            return wait.IsCompleted
                ? _releaser
                : wait.ContinueWith((_, state) => new Releaser((AsyncLocker)state),
                    this,
                    CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously,
                    TaskScheduler.Default);
        }

        /// <summary>
        /// 释放资源的包装
        /// </summary>
        public readonly struct Releaser : IDisposable
        {
            //字段
            private readonly AsyncLocker _toRelease;

            /// <summary>
            /// 释放器
            /// </summary>
            /// <param name="toRelease"></param>
            internal Releaser(AsyncLocker toRelease)
            {
                _toRelease = toRelease;
            }

            /// <summary>
            /// 执行与释放、释放或重置非托管资源相关联的应用程序定义的任务
            /// </summary>
            /// <filterpriority>2</filterpriority>
            public readonly void Dispose()
            {
                _toRelease?._semaphore.Release();
            }

        }

    }
}